package com.cloud.sysmana.ser.impl;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cloud.sysmana.dto.FuncExport;
import com.cloud.sysmana.dto.FuncTree;
import com.cloud.sysmana.entity.SysFunc;
import com.cloud.sysmana.entity.SysRole;
import com.cloud.sysmana.entity.dao.ISysFuncDao;
import com.cloud.sysmana.entity.dao.ISysRoleDao;
import com.cloud.sysmana.entity.dao.ISysRoleFuncDao;
import com.cloud.sysmana.ser.ISysFuncService;
import com.cloud.util.base.RetType;
import com.cloud.util.date.DateUtil;
import com.cloud.util.jsTree.JsTreeJson;
import com.cloud.util.jsTree.JsTreeUtil;
import com.cloud.util.jsTree.JsTreeUtil.IObjectToJsTree;
import com.cloud.util.other.FileUtil;
import com.cloud.util.other.StringUtil;

/**
 * 系统功能Service
 * @author gaof
 * @date 2016年4月17日
 */
@Service
@Transactional
public class SysFuncService implements ISysFuncService {

	/* 功能、岗位数据缓存 */
	@Resource(name="funcRoleCache")
	private FuncRoleCacheService funcRoleCache;
	
	@Resource(name="sysFuncDao")
	private ISysFuncDao sysFuncDao;
	
	@Resource(name="sysRoleDao")
	private ISysRoleDao sysRoleDao;
	
	@Resource(name="sysRoleFuncDao")
	private ISysRoleFuncDao sysRoleFuncDao;
	
	/**
	 * 添加或更新系统功能
	 * @param func
	 * @return
	 */
	@Override
	public RetType addOrUpdateFunc(SysFunc func) {
		
		if (func.getPid() == null) {
			func.setPid(0);
		}
		sysFuncDao.addOrUpdateFunc(func);
		
		/*更新功能缓存*/
		funcRoleCache.reloadFunc();
		/*更新岗位权限缓存*/
		funcRoleCache.reloadRoleFunc();
		
		RetType reType = new RetType();
		reType.setErrCode(RetType.RET_SUCCESS);
		
		return reType;
	}

	/**
	 * 获得功能菜单Json数据
	 * @return
	 */
	@Override
	public String listFuncTreeJson() {
		
		/* 系统功能结构信息 */
		FuncTree funcTree = new FuncTree();
		SysFunc func = new SysFunc();
		func.setFuncId(0);//根目录为0
		func.setFuncName("功能结构列表Root");
		funcTree.setFunc(func);
		List<SysFunc> funcList = new ArrayList<SysFunc>();
		funcList.addAll(funcRoleCache.getFucList());
		funcTree = funcRoleCache.getFuncTree(funcTree, funcList);
		
		/* 加入根功能信息 */
		JSONArray jsonTree = new JSONArray();
		JSONObject rootObject = new JSONObject();
		rootObject.put("id", 0);
		rootObject.put("pId", -1);
		rootObject.put("name", "功能结构列表Root");
		rootObject.put("funcOrde", 1);
		rootObject.put("funcUrl", "root");
		rootObject.put("open", true);
		jsonTree.add(rootObject);
		
		/* 系统功能结构 */
		jsonTree = FuncTree.printFunc(funcTree, jsonTree);
		
		return jsonTree.toString();
	}

	/**
	 * 删除功能菜单及子功能
	 * @param func
	 * @return
	 */
	@Override
	public void delLinkFunc(SysFunc func) {
		
		List<SysFunc> listFunc = new ArrayList<SysFunc>();
		int id = func.getFuncId();
		
		//如果是选择跟目录
		if (id <= 0) {
			//获取该功能下的所有子功能
			listFunc.addAll(getAllChildFunc(func));
		}else{
			SysFunc funcDb = funcRoleCache.getFuncById(id);
			listFunc.add(funcDb);
			//获取该功能下的所有子功能
			listFunc.addAll(getAllChildFunc(funcDb));
		}
		
		//删除本功能和所有子功能
		sysFuncDao.delFuncs(listFunc);
		
		//删除功能对应授权
		for (SysFunc sysFunc : listFunc) {
			sysRoleFuncDao.delRoleFuncByFuncId(sysFunc.getFuncId());
		}
		
		/*更新功能缓存*/
		funcRoleCache.reloadFunc();
		/*更新岗位权限缓存*/
		funcRoleCache.reloadRoleFunc();
	}

	/**
	 * 获取功能的所有下级功能
	 * @param func
	 * @return
	 */
	private List<SysFunc> getAllChildFunc(SysFunc func) {
		
		List<SysFunc> funcList = new ArrayList<SysFunc>();
		getChildFunc(func, funcList);
		
		return funcList;
	}

	/**
	 * 获取下级功能
	 * @param func
	 * @param funcList
	 */
	private void getChildFunc(SysFunc func, List<SysFunc> funcList) {
		
		List<SysFunc> childList = sysFuncDao.listFuncByPid(func.getFuncId());
		if(childList != null && !childList.isEmpty()){
			funcList.addAll(childList);
			
			for (SysFunc funcItem : childList) {
				getChildFunc(funcItem, funcList);
			}
		}
	}

	/**
	 * 获取功能岗位Json数据
	 * @param role 
	 * @return
	 */
	@Override
	public String listRoleTreeJson(SysRole role) {
		
		role = sysRoleDao.getRoleById(role.getRoleId());
		if(role == null){
			return "";
		}
		
		/* 系统功能结构信息 */
		FuncTree funcTree = new FuncTree();
		SysFunc func = new SysFunc();
		func.setFuncId(0);//根目录为0
		func.setFuncName("功能结构列表Root");
		funcTree.setFunc(func);
		List<SysFunc> funcList = sysFuncDao.listFuncNeedAuth();//获取所有需要授权的功能
		//List<SysFunc> funcList = new ArrayList<SysFunc>();
		//funcList.addAll(funcRoleCache.getFucList());
		funcTree = funcRoleCache.getFuncTree(funcTree, funcList);
		
		/* 加入根功能信息 */
		JSONArray jsonTree = new JSONArray();
		JSONObject rootObject = new JSONObject();
		rootObject.put("id", 0);
		rootObject.put("pId", -1);
		rootObject.put("name", "功能结构列表Root");
		rootObject.put("funcOrde", 1);
		rootObject.put("funcUrl", "root");
		rootObject.put("open", true);
		rootObject.put("funcCheck", false);
		jsonTree.add(rootObject);
		
		//根据岗位id获得其所包含功能的id
		List<Integer> funcIdList = funcRoleCache.getRoleFuncIdByRoleId(role.getRoleId());
		JSONArray treeArray = FuncTree.printFuncCheck(funcTree, funcIdList, jsonTree);
		
		return treeArray.toString();
	}

	/**
	 * 功能导出
	 * @param request
	 * @param response
	 * @param exportId
	 */
	@Override
	public void funcOutput(HttpServletRequest request,
			HttpServletResponse response, String exportId) {
		
		String nowStr = DateUtil.getDatebyYMDHMS();
		String fileName="功能导出_" + nowStr + ".txt";
		fileName = StringUtil.getDownChinaName(fileName);
        
        response.reset();// 不加这一句的话会出现下载错误 
        response.setHeader("Content-disposition", "attachment; filename="+fileName);// 设定输出文件头   
        response.setContentType("text/x-plain");// 定义输出类型 
        
        ServletOutputStream out = null;
        BufferedOutputStream buff = null;     
        
        try {
            out = response.getOutputStream();
            buff = new BufferedOutputStream(out);
            
            //获取需要导出的数据
            List<SysFunc> exportList = null;
            SysFunc funcDb = null;
            if(StringUtil.isEmpty(exportId)){//没有id，则导出所有功能
            	exportList = funcRoleCache.getFucList();
            	
            }else{//有id，导出id对应功能及其子功能
            	funcDb = funcRoleCache.getFuncById(StringUtil.StringToInt(exportId, 0));
            	exportList = new ArrayList<SysFunc>();
            	exportList.add(funcDb);
    			//获取该功能下的所有子功能
            	exportList.addAll(getAllChildFunc(funcDb));
            }
            
            //生成树形结构
            JsTreeJson jsTree = new JsTreeJson();
            if(StringUtil.isEmpty(exportId)){//没有id，则根功能为0
            	jsTree.setId("0");//根节点
        		jsTree.setText("根功能");
            }else{//有id，则跟功能为
            	jsTree.setId(funcDb.getPid().toString());//根节点
        		jsTree.setText("根功能");
            }
            if(exportList != null && !exportList.isEmpty()){
            	jsTree = JsTreeUtil.getJsTree(jsTree, exportList, new IObjectToJsTree() {
					@Override
					public JsTreeJson objectToJsTree(Object obj) {
						SysFunc req = (SysFunc) obj;
						JsTreeJson tree = getJsTreeJson(req);
						return tree;
					}
					
					@Override
					public String getObjectPId(Object obj) {
						SysFunc req = (SysFunc) obj;
						return String.valueOf(req.getPid());
					}
				});
            }
            
            buff.write(JSON.toJSONString(jsTree).getBytes("UTF-8"));
            buff.flush();     
            buff.close();
            buff = null;
            out.flush();
            out.close();
            out = null;
            
        } catch (Exception e) {
            e.printStackTrace();
            
        }finally{
        	if(out != null){
        		try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
        	
        	if(buff != null){
        		try {
        			buff.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
        	
        }
		
	}

	/**
	 * 对象转JsTreeJson
	 * @param req
	 * @return
	 */
	protected JsTreeJson getJsTreeJson(SysFunc req) {
		
		JsTreeJson tree = new JsTreeJson();
		tree.setId(req.getFuncId().toString());
		tree.setText(req.getFuncName());
		
		FuncExport func = new FuncExport();
		func.setAcceType(req.getAcceType());
		func.setFuncName(req.getFuncName());
		func.setFuncUrl(req.getFuncUrl());
		func.setIcon(req.getIcon());
		func.setSeq(req.getSeq());
		func.setType(req.getType());
		
		//a标签附带参数
		tree.setA_attr(func);
		
		return tree;
	}

	/**
	 * 功能导入
	 * @param request
	 * @param file
	 * @param importId
	 */
	@Override
	public void funcImput(HttpServletRequest request, MultipartFile[] file, String importId) {
		
		// 文件校验
		if (file == null || file.length == 0) {
			return ;
		}
		for (MultipartFile myfile : file) {
			//文件不能为空
			if (myfile == null || myfile.isEmpty()) {
				return ;
			}
			
			//只识别txt格式文件
			String fileType = FileUtil.getFileTypeLower(myfile.getOriginalFilename());
			if(!"txt".equals(fileType)){
				System.out.println("文件格式不正确！");
				return ;
			}
			
		}
		
		// 遍历文件储存
		for (int i = 0; i < file.length; i++) {
			MultipartFile myfile = file[i];

			// 处理导入
			doFuncImport(myfile, importId);
		}
		
		/*更新功能缓存*/
		funcRoleCache.reloadFunc();
	}

	/**
	 * 处理导入
	 * @param myfile
	 * @param importId 
	 */
	private void doFuncImport(MultipartFile myfile, String importId) {
		
		try {
			//读取文件流
			BufferedReader br = new BufferedReader(new InputStreamReader(
					myfile.getInputStream()));

			String line = null;
			StringBuilder str = new StringBuilder();
			//读取文件内容
			while ((line = br.readLine()) != null) {
				str.append(line);
			}

			//转换成功能树
			JsTreeJson funcTree = JSON.parseObject(str.toString(),
					JsTreeJson.class);
			
			//最外层为跟目录，从最外层的children开始才是正式功能树，跟
			if(StringUtil.isEmpty(importId)){
				importFuncList(funcTree.getChildren(), "0");
			}else{
				importFuncList(funcTree.getChildren(), importId);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	/**
	 * 遍历功能列表并导入
	 * @param children 功能树
	 * @param pid 父id
	 */
	private void importFuncList(List<JsTreeJson> jsTreeList, String pid) {
		
		//判空
		if(jsTreeList == null || jsTreeList.isEmpty()){
			return ;
		}
		
		//递归遍历
		for (JsTreeJson jsTree : jsTreeList) {
			FuncExport func = JSON.parseObject(jsTree.getA_attr().toString(), FuncExport.class);
			
			SysFunc sysFunc = new SysFunc();
			sysFunc.setPid(StringUtil.StringToInt(pid, 0));
			sysFunc.setAcceType(func.getAcceType());
			sysFunc.setFuncName(func.getFuncName());
			sysFunc.setFuncUrl(func.getFuncUrl());
			sysFunc.setIcon(func.getIcon());
			sysFunc.setSeq(func.getSeq());
			sysFunc.setType(func.getType());
			sysFunc = sysFuncDao.addFunc(sysFunc);
			
			importFuncList(jsTree.getChildren(), sysFunc.getFuncId().toString());
		}
		
	}

}
